#pragma once
#include "Mutex.hpp"
#include <iostream>
#include <string>
#include <filesystem>
#include <fstream>
#include <memory>
#include <sstream>
const std::string gsep = "\r\n";
// 策略模式，C++多态特性
// 2. 刷新策略 a: 显示器打印 b:向指定的文件写入
//  刷新策略基类
class LogStrategy
{
public:
    ~LogStrategy() = default;
    virtual void SyncLog(const std::string &message) = 0;
};

// 显示器打印日志的策略 : 子类
class ConsoleLogStrategy : public LogStrategy
{
public:
    ConsoleLogStrategy()
    {
    }
    void SyncLog(const std::string &message) override
    {
        LockGuard lockguard(_mutex);
        std::cout << message << gsep;
    }
    ~ConsoleLogStrategy()
    {
    }

private:
    Mutex _mutex;
};

// 文件打印日志的策略 : 子类
const std::string defaultpath = "./log";
const std::string defaultfile = "my.log";
class FileLogStrategy : public LogStrategy
{
public:
    FileLogStrategy(const std::string &path = defaultpath, const std::string &file = defaultfile)
        : _path(path),
          _file(file)
    {
        LockGuard lockguard(_mutex);
        if (std::filesystem::exists(_path))
        {
            return;
        }
        try
        {
            std::filesystem::create_directories(_path);
        }
        catch (const std::filesystem::filesystem_error &e)
        {
            std::cerr << e.what() << '\n';
        }
    }
    void SyncLog(const std::string &message) override
    {
        LockGuard lockguard(_mutex);

        std::string filename = _path + (_path.back() == '/' ? "" : "/") + _file; // "./log/" + "my.log"
        std::ofstream out(filename, std::ios::app);                              // 追加写入的 方式打开
        if (!out.is_open())
        {
            return;
        }
        out << message << gsep;
        out.close();
    }
    ~FileLogStrategy()
    {
    }

private:
    std::string _path; // 日志文件所在路径
    std::string _file; // 日志文件本身
    Mutex _mutex;
};

// 枚举日志等级
enum class LogLevel
{
    DEBUG,
    INFO,
    WARNING,
    ERROR,
    FATAT
}; // 这些本质还都是数子，我要的还是string

std::string Level2Str(LogLevel loglevel)
{
    switch (loglevel)
    {
    case LogLevel::DEBUG:
        return "DEBUG";
    case LogLevel::INFO:
        return "INFO";
    case LogLevel::WARNING:
        return "WARNING";
    case LogLevel::ERROR:
        return "ERROR";
    case LogLevel::FATAT:
        return "FATAT";

    default:
        return "UNKNOWN";
    }
}

std::string GetTimeStamp()
{
  time_t curr = time(nullptr);
        struct tm curr_tm;
        localtime_r(&curr, &curr_tm);
        char timebuffer[128];
        snprintf(timebuffer, sizeof(timebuffer),"%4d-%02d-%02d %02d:%02d:%02d",
            curr_tm.tm_year+1900,
            curr_tm.tm_mon+1,
            curr_tm.tm_mday,
            curr_tm.tm_hour,
            curr_tm.tm_min,
            curr_tm.tm_sec
        );
        return timebuffer;
    }

class Logger
{
    public:
    Logger()
    {
        EnableConsoleLogStrategy();
    }
    void EnableFileLogStrategy()
    {
        _fflush_strategy = std::make_unique<FileLogStrategy>();
    }

    void EnableConsoleLogStrategy()
    {
        _fflush_strategy = std::make_unique<ConsoleLogStrategy>();
    }
    // 在这里创建内部类
    class LogMessage
    {
public:
        LogMessage(LogLevel &level, std::string &src_name, int line_number, Logger &logger)
            : _curr_time(GetTimeStamp()), 
            _level(level),
              _src_name(src_name),
              _line_number(line_number),
              _logger(logger)
        {
            std::stringstream ss;
            ss << "[" << _curr_time << "] "
               << "[" << Level2Str(_level) << "] "
               << "[" << _pid << "] "
               << "[" << _src_name << "] "
               << "[" << _line_number << "] "
               << "- ";
            _loginfo = ss.str();
        }

          template <typename T>
            LogMessage &operator<<(const T &info)
            {
                // a = b = c =d;
                // 日志的右半部分,可变的
                std::stringstream ss;
                ss << info;
                _loginfo += ss.str();
                return *this;
            }
        ~LogMessage() {
            
                if (_logger._fflush_strategy)
                {
                    _logger._fflush_strategy->SyncLog(_loginfo);
                }
        }

    private:
        std::string _curr_time;
        LogLevel _level;
        pid_t _pid;
        std::string _src_name;
        int _line_number;
        std::string _loginfo; // 合并之后，一条完整的信息
        Logger &_logger;
    };
     // 这里故意写成返回临时对象
        LogMessage operator()(LogLevel level, std::string name, int line)
        {
            return LogMessage(level, name, line, *this);
        }
    ~Logger() {}

private:
    std::unique_ptr<LogStrategy> _fflush_strategy;
};

// const std::string gsep = "\r\n";
// class xulog{
//     public:
// ~xulog(){}
// virtual void xulogfun(std::string&massage)=0;
// };
// //显示器打印策略
// class xiansqlog :public xulog
// {
// public:
// xiansqlog(){}
// void xulogfun(std::string&massage) override
// {
// //线程一个一个调用这个函数
// LockGuard lockguard(_mutex);
// //向显示器里面打印
// std::cout<<massage<<gsep;

// }
// ~xiansqlog(){}

// private:
// Mutex _mutex;

// };

// //向文件里面打印

//   const std::string defaultpath = "./log";
//     const std::string defaultfile = "my.log";
// class wenjlog :public xulog
// {
//     public:
// wenjlog(std::string path=defaultpath,std::string file=defaultfile)
//      : _path(path),
//               _file(file)
//         {
//             LockGuard lockguard(_mutex);
//             if (std::filesystem::exists(_path))
//             {
//                 return;
//             }
//             try
//             {
//                 std::filesystem::create_directories(_path);
//             }
//             catch (const std::filesystem::filesystem_error &e)
//             {
//                 std::cerr << e.what() << '\n';
//             }
//         }

// void xulogfun(std::string& message) override
// {
//      {
//             LockGuard lockguard(_mutex);

//             std::string filename = _path + (_path.back() == '/' ? "" : "/") + _file; // "./log/" + "my.log"
//             std::ofstream out(filename, std::ios::app);                              // 追加写入的 方式打开
//             if (!out.is_open())
//             {
//                 return;
//             }
//             out << message << gsep;
//             out.close();
//         }
// }

// // {
// //         // 首先应该打开应该文件
// //         // LockGuard lockguard(_mutex); // 如果需要线程安全，取消注释

// //         // std::string filename = _path + (_path.back() == '/' ? "" : "/") + _file;
// //         // std::ofstream out(filename, std::ios::app);
// //         // if (!out.is_open()) {
// //         //     return;
// //         // }
// //         // out << massage << gsep;
// //         // out.close();
// //         std::cout<<"haha";
// //     }
// ~wenjlog(){}
// private:
// std::string _path;
// std::string _file;
// Mutex _mutex;
// };

// //开始建立一个真正的日志
